<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
<meta name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">

    <meta name="author" content="baifangzi">




    <meta name="keywords" content="白房子">


<title>JS基础知识总结 | 白房子的博客</title>



    <link rel="icon" href="/favicon.ico">




    <!-- stylesheets list from _config.yml -->
    
    <link rel="stylesheet" href="/css/style.css">
    



    <!-- scripts list from _config.yml -->
    
    <script src="/js/script.js"></script>
    
    <script src="/js/tocbot.min.js"></script>
    



    
    
        
    


<meta name="generator" content="Hexo 4.2.1"></head>
<body class="dark-theme">
    <div class="wrapper">
        <header>
    <nav class="navbar">
        <div class="container">
            <div class="navbar-header header-logo"><a href="/">白房子的博客</a></div>

            <div class="menu navbar-right">
                
                    <a class="menu-item" href="/search">站内搜索</a>
                
                    <a class="menu-item" href="/archives">文章</a>
                
                    <a class="menu-item" href="/categories">分类</a>
                
                    <a class="menu-item" href="/tags">标签</a>
                
                    <a class="menu-item" href="/tools">工具</a>
                
                    <a class="menu-item" href="/about.html">关于</a>
                

            </div>
        </div>
    </nav>

    
    <nav class="navbar-mobile" id="nav-mobile">
        <div class="container">
            <div class="navbar-header">
                <div>
                    <a href="/">白房子的博客</a><a id="mobile-toggle-theme">路&nbsp;</a>
                </div>
                <div class="menu-toggle" onclick="mobileBtn()">&#9776; Menu</div>
            </div>
            <div class="menu" id="mobile-menu">
                
                    <a class="menu-item" href="/search">站内搜索</a>
                
                    <a class="menu-item" href="/archives">文章</a>
                
                    <a class="menu-item" href="/categories">分类</a>
                
                    <a class="menu-item" href="/tags">标签</a>
                
                    <a class="menu-item" href="/tools">工具</a>
                
                    <a class="menu-item" href="/about.html">关于</a>
                
            </div>
        </div>
    </nav>

</header>
<script>
    var mobileBtn = function f() {
        var toggleMenu = document.getElementsByClassName("menu-toggle")[0];
        var mobileMenu = document.getElementById("mobile-menu");
        if(toggleMenu.classList.contains("active")){
           toggleMenu.classList.remove("active")
            mobileMenu.classList.remove("active")
        }else{
            toggleMenu.classList.add("active")
            mobileMenu.classList.add("active")
        }
    }
</script>
        <div class="main">
            <div class="container">
    
    
        <div class="post-toc">
    <div class="tocbot-list">
    </div>
    <div class="tocbot-list-menu">
        <a class="tocbot-toc-expand" onclick="expand_toc()">全部展开</a>
        <a onclick="go_top()">返回顶部</a>
        <a onclick="go_bottom()">返回底部</a>
    </div>
</div>

<script>
    document.ready(
        function () {
            tocbot.init({
                tocSelector: '.tocbot-list',
                contentSelector: '.post-content',
                headingSelector: 'h1, h2, h3, h4, h5',
                collapseDepth: 1,
                orderedList: false,
                scrollSmooth: true,
            })
        }
    )

    function expand_toc() {
        var b = document.querySelector(".tocbot-toc-expand");
        tocbot.init({
            tocSelector: '.tocbot-list',
            contentSelector: '.post-content',
            headingSelector: 'h1, h2, h3, h4, h5',
            collapseDepth: 6,
            orderedList: false,
            scrollSmooth: true,
        });
        b.setAttribute("onclick", "collapse_toc()");
        b.innerHTML = "全部折叠"
    }

    function collapse_toc() {
        var b = document.querySelector(".tocbot-toc-expand");
        tocbot.init({
            tocSelector: '.tocbot-list',
            contentSelector: '.post-content',
            headingSelector: 'h1, h2, h3, h4, h5',
            collapseDepth: 1,
            orderedList: false,
            scrollSmooth: true,
        });
        b.setAttribute("onclick", "expand_toc()");
        b.innerHTML = "全部展开"
    }

    function go_top() {
        window.scrollTo(0, 0);
    }

    function go_bottom() {
        window.scrollTo(0, document.body.scrollHeight);
    }

</script>
    

    
    <article class="post-wrap">
        <header class="post-header">
            <h1 class="post-title">JS基础知识总结</h1>
            
                <div class="post-meta">
                    
                        作者: <a itemprop="author" rel="author" href="/">baifangzi</a>
                    

                    
                        <span class="post-time">
                        日期: <a href="#">四月 24, 2019&nbsp;&nbsp;15:40:24</a>
                        </span>
                    
                    
                        <span class="post-category">
                    Category:
                            
                                <a href="/category/%E5%9F%BA%E7%A1%80/">基础</a>
                            
                        </span>
                    
                </div>
            
        </header>

        <div class="post-content">
            <h2 id="原型原型链"><a href="#原型原型链" class="headerlink" title="原型原型链"></a>原型原型链</h2><ul>
<li>参照 <a href="https://juejin.cn/post/6976958624207732772" target="_blank" rel="noopener">js原型与原型链解析</a></li>
</ul>
<h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2><ul>
<li>参照 <a href="https://juejin.cn/post/6977329572417110024" target="_blank" rel="noopener">js的几种继承方式</a></li>
</ul>
<h2 id="call，apply，bind用法及实现"><a href="#call，apply，bind用法及实现" class="headerlink" title="call，apply，bind用法及实现"></a>call，apply，bind用法及实现</h2><ul>
<li>作用：简单来说就是改变<code>this</code>的指向，在一个对象中调用另一个对象的方法</li>
</ul>
<h3 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h3><ul>
<li><code>apply</code>与<code>call</code>的用法相似，会直接执行函数</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">A.sayName.call(B,<span class="string">'tom'</span>)</span><br><span class="line">A.sayName.apply(B,[<span class="string">'tom'</span>])</span><br></pre></td></tr></table></figure>

<ul>
<li><code>bind</code>用法与<code>call</code>相似，不同的是，她不会立即执行，他会返回原函数的拷贝</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> bSay = A.sayName.bind(B,<span class="string">'tom'</span>) <span class="comment">//拷贝</span></span><br><span class="line">bSay()<span class="comment">//调用</span></span><br></pre></td></tr></table></figure>

<h3 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//A.myCall(B,arg1,arg2)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//挂载到Function 的原型对象上，以便继承给函数对象调用</span></span><br><span class="line"><span class="built_in">Function</span>.prototype.myCall = <span class="function"><span class="keyword">function</span> (<span class="params">originFun, ...args</span>) </span>&#123;</span><br><span class="line">	<span class="comment">//A点出的myCall，这里this 指向A函数</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="keyword">this</span>)</span><br><span class="line">    <span class="comment">//在B里面定义一个私有属性指向A函数</span></span><br><span class="line">    originFun.__thisFn__ = <span class="keyword">this</span></span><br><span class="line">    <span class="comment">//B调用A函数，this指向B</span></span><br><span class="line">    <span class="keyword">let</span> result = originFun.__thisFn__(...args) </span><br><span class="line">    <span class="comment">//删除无用属性</span></span><br><span class="line">    <span class="keyword">delete</span> originFun.__thisFn__</span><br><span class="line">    <span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="判断类型的方法"><a href="#判断类型的方法" class="headerlink" title="判断类型的方法"></a>判断类型的方法</h2><ul>
<li><p><code>typeof</code>与<code>instanceof</code></p>
</li>
<li><p><code>Object.prototype.toString.call()</code>;每个对象都存在<code>toString()</code>方法，默认情况下，被每个<code>Object</code>对象继承，如果未被覆盖，会返回<code>[object type]</code>,<code>type</code>是对象的类型。比如：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj= <span class="keyword">new</span> <span class="built_in">Object</span>()</span><br><span class="line">obj.toString() <span class="comment">//输出 "[object Object]"</span></span><br></pre></td></tr></table></figure>

<p>但是对于其他情况</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr =<span class="keyword">new</span> <span class="built_in">Array</span>(<span class="number">1</span>,<span class="number">2</span>)</span><br><span class="line">arr.toString() <span class="comment">// 输出 "1,2"</span></span><br></pre></td></tr></table></figure>

<p> 这是因为所谓的<code>Array</code>、<code>String</code>等类型在继承于基类<code>Object</code>时，重写了<code>toString</code>方法，在调用的时候，通过原型链向上查找方法时，找到<code>Array</code>上面的<code>toString</code>就停止查找，直接调用了，所以输出与预想的有偏差，那如何让<code>arr</code>去调用<code>Object</code>上面的该方法呢？显而易见借用<code>call()</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>.prototype.toString.call(arr) <span class="comment">// 输出 "[object Array]"</span></span><br></pre></td></tr></table></figure>

<p>然后在利用 <code>slice</code>方法截取出来类型</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 是否字符串</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isString = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'String'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否数字</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isNumber = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Number'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否boolean</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isBoolean = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Boolean'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否函数</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isFunction = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Function'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否为null</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isNull = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Null'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否undefined</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isUndefined = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Undefined'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否对象</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isObj = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Object'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否数组</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isArray = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Array'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否时间</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isDate = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Date'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否正则</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isRegExp = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'RegExp'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否错误对象</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isError = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Error'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否Symbol函数</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isSymbol = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Symbol'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 是否Promise对象</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> isPromise = <span class="function">(<span class="params">o</span>) =&gt;</span> <span class="built_in">Object</span>.prototype.toString.call(o).slice(<span class="number">8</span>, <span class="number">-1</span>) === <span class="string">'Promise'</span></span><br></pre></td></tr></table></figure>

</li>
</ul>
<h2 id="捕获与冒泡"><a href="#捕获与冒泡" class="headerlink" title="捕获与冒泡"></a>捕获与冒泡</h2><ul>
<li>事件捕获与冒泡过程</li>
</ul>
<p><img src="https://gitee.com/baifangzi/blogimage/raw/master/img/20210701104839.png" alt="image-20210701104838356"></p>
<h3 id="捕获"><a href="#捕获" class="headerlink" title="捕获"></a>捕获</h3><ul>
<li><p>事件捕获阶段，会由外到内，一层一层的检查是否注册了事件</p>
</li>
<li><p>如何在捕获阶段注册事件？</p>
<ul>
<li>使用 <code>addEventListener</code>注册事件，第三个参数代表是否在捕获阶段处理事件，设置为<code>true</code></li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"box"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">"btn"</span>&gt;</span>按钮<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript">    <span class="comment">//先显示div 后显示btn</span></span></span><br><span class="line"><span class="javascript">    <span class="keyword">const</span> box = <span class="built_in">document</span>.querySelector(<span class="string">'.box'</span>)</span></span><br><span class="line">    box.addEventListener(</span><br><span class="line"><span class="actionscript">        <span class="string">'click'</span>,</span></span><br><span class="line">        () =&gt; &#123;</span><br><span class="line"><span class="actionscript">            alert(<span class="string">'div被点击了'</span>)</span></span><br><span class="line">        &#125;,</span><br><span class="line"><span class="actionscript">        <span class="literal">true</span></span></span><br><span class="line">    )</span><br><span class="line"><span class="javascript">    <span class="keyword">const</span> btn = <span class="built_in">document</span>.querySelector(<span class="string">'.btn'</span>)</span></span><br><span class="line">    btn.addEventListener(</span><br><span class="line"><span class="actionscript">        <span class="string">'click'</span>,</span></span><br><span class="line">        () =&gt; &#123;</span><br><span class="line"><span class="actionscript">            alert(<span class="string">'button被点击了'</span>)</span></span><br><span class="line">        &#125;,</span><br><span class="line"><span class="actionscript">        <span class="literal">true</span></span></span><br><span class="line">    )</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

</li>
</ul>
<h3 id="冒泡"><a href="#冒泡" class="headerlink" title="冒泡"></a>冒泡</h3><ul>
<li><p>与捕获相反，在事件冒泡阶段，会从里到外来检查是否注册事件</p>
</li>
<li><p>默认情况下，所有的事件都是在冒泡阶段进行注册，如何阻止事件冒泡？</p>
<ul>
<li><p>w3标准</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">event.stopPropagation()</span><br></pre></td></tr></table></figure>
</li>
<li><p>IE浏览器</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">event.cancelBubble=<span class="literal">true</span></span><br></pre></td></tr></table></figure>

</li>
</ul>
</li>
</ul>
<h2 id="事件委托"><a href="#事件委托" class="headerlink" title="事件委托"></a>事件委托</h2><ul>
<li>多个元素注册了相同的事件，可以把这些事件委托到它的父元素上，比较常见的是<code>ul</code>里面的<code>li</code>标签点击事件</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span>1<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span>2<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span>3<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span>4<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span>5<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">const</span> ul = <span class="built_in">document</span>.querySelector(<span class="string">'ul'</span>)</span></span><br><span class="line"><span class="actionscript">    ul.addEventListener(<span class="string">'click'</span>, (e) =&gt; &#123;</span></span><br><span class="line"><span class="actionscript">        <span class="keyword">if</span> (e.target.nodeName == <span class="string">'LI'</span>) &#123;</span></span><br><span class="line">            alert(e.target.innerText)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="闭包问题"><a href="#闭包问题" class="headerlink" title="闭包问题"></a>闭包问题</h2><ul>
<li>在一个内层函数中访问到外层函数的作用域</li>
</ul>
<h3 id="隔离作用域"><a href="#隔离作用域" class="headerlink" title="隔离作用域"></a>隔离作用域</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> makeCounter = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> privateCounter = <span class="number">0</span>;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">changeBy</span>(<span class="params">val</span>) </span>&#123;</span><br><span class="line">    privateCounter += val;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    increment: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      changeBy(<span class="number">1</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">    decrement: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      changeBy(<span class="number">-1</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">    value: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> privateCounter;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Counter1与Counter2互不影响，在闭包内修改变量，不会影响到另一个闭包中的变量</span></span><br><span class="line"><span class="keyword">var</span> Counter1 = makeCounter();</span><br><span class="line"><span class="keyword">var</span> Counter2 = makeCounter();</span><br><span class="line"><span class="built_in">console</span>.log(Counter1.value()); <span class="comment">/* logs 0 */</span></span><br><span class="line">Counter1.increment();</span><br><span class="line">Counter1.increment();</span><br><span class="line"><span class="built_in">console</span>.log(Counter1.value()); <span class="comment">/* logs 2 */</span></span><br><span class="line">Counter1.decrement();</span><br><span class="line"><span class="built_in">console</span>.log(Counter1.value()); <span class="comment">/* logs 1 */</span></span><br><span class="line"><span class="built_in">console</span>.log(Counter2.value()); <span class="comment">/* logs 0 */</span></span><br></pre></td></tr></table></figure>

<h3 id="经典for循环闭包问题"><a href="#经典for循环闭包问题" class="headerlink" title="经典for循环闭包问题"></a>经典for循环闭包问题</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>, arr = []; i &lt; <span class="number">5</span>; i++) &#123;</span><br><span class="line">    setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(i)</span><br><span class="line">    &#125;, <span class="number">500</span>)</span><br><span class="line">&#125;<span class="comment">// 5,5,5,5</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//使用闭包</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>, arr = []; i &lt; <span class="number">5</span>; i++) &#123;</span><br><span class="line">    ;(<span class="function"><span class="keyword">function</span> (<span class="params">i</span>) </span>&#123;</span><br><span class="line">        setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(i)</span><br><span class="line">        &#125;, <span class="number">1000</span> * i)</span><br><span class="line">    &#125;)(i)</span><br><span class="line">&#125;<span class="comment">//1,2,3,4</span></span><br></pre></td></tr></table></figure>

<h2 id="new对象时发生了什么，实现一个new"><a href="#new对象时发生了什么，实现一个new" class="headerlink" title="new对象时发生了什么，实现一个new"></a>new对象时发生了什么，实现一个new</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> myNew = <span class="function">(<span class="params">constructorFn, ...args</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 创建一个新的对象</span></span><br><span class="line">  <span class="keyword">let</span> obj = &#123;&#125;</span><br><span class="line">  <span class="comment">// 创建一个私有属性，指向构造函数的原型对象</span></span><br><span class="line">  obj.__proto__ = constructorFn.prototype</span><br><span class="line">  <span class="comment">// 执行构造函数</span></span><br><span class="line">  constructorFn.call(obj, ...args)</span><br><span class="line">  <span class="comment">//返回这个对象</span></span><br><span class="line">  <span class="keyword">return</span> obj</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.name = name</span><br><span class="line">  <span class="keyword">this</span>.age = age</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> Per1 = <span class="keyword">new</span> Person(<span class="string">'Tom'</span>, <span class="number">12</span>)</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">'Per1'</span>, Per1)</span><br><span class="line"><span class="keyword">const</span> Per2 = myNew(Person, <span class="string">'Tom'</span>, <span class="number">12</span>)</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">'Per2'</span>,Per2)</span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/baifangzi/blogimage/raw/master/img/20210701174621.png" alt="image-20210701174620575"></p>
<h2 id="防抖与节流"><a href="#防抖与节流" class="headerlink" title="防抖与节流"></a>防抖与节流</h2><ul>
<li><a href="https://juejin.cn/post/6951951053214449701#heading-5" target="_blank" rel="noopener">防抖与节流的实现</a> </li>
</ul>
<p>​    </p>
<h3 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a>闭包</h3><h2 id="深浅拷贝"><a href="#深浅拷贝" class="headerlink" title="深浅拷贝"></a>深浅拷贝</h2><ul>
<li>基本类型 <code>String</code>、<code>Number</code>等都是<strong>按值</strong>访问的，它的值存储在栈中</li>
<li>引用类型都是 <strong>按引用</strong>访问的，它将引用地址存储在栈上，然后再去堆上开辟空间存放他们的值</li>
</ul>
<h3 id="浅拷贝"><a href="#浅拷贝" class="headerlink" title="浅拷贝"></a>浅拷贝</h3><ul>
<li>如果是基本类型，就直接拷贝基本类型的值，如果是引用类型，就拷贝引用类型的引用地址</li>
<li>浅拷贝对于基本类型来说，他们之间改变值不会相互影响，但是对于引用类型来说，由于拷贝的是地址，这些地址最终都指向同一个堆里面，所以会互相影响</li>
</ul>
<h4 id="实现方式"><a href="#实现方式" class="headerlink" title="实现方式"></a>实现方式</h4><ul>
<li>ES6展开运算符</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj1 =&#123;<span class="attr">name</span>:<span class="string">'tom'</span>,<span class="attr">age</span>:<span class="number">12</span>,<span class="attr">addr</span>:&#123;<span class="attr">lng</span>:<span class="number">26.0</span>,<span class="attr">lag</span>:<span class="number">45.0</span>&#125;,<span class="attr">friends</span>:[<span class="string">'john'</span>,<span class="string">'jerry'</span>]&#125;</span><br><span class="line"><span class="keyword">let</span> obj2=&#123;...obj1&#125;</span><br><span class="line">obj2.name=<span class="string">'jerry'</span></span><br><span class="line">obj2.frinds[<span class="number">0</span>]=<span class="string">'tom'</span></span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/baifangzi/blogimage/raw/master/img/20210702095036.png" alt="image-20210702095035320"></p>
<p>ES6展开运算符对于不同结构的数据，存在不同的表现.<strong>对于一维的对象或者数组，进行的深拷贝，对于多维的对象或者数组进行的是浅拷贝</strong></p>
<ul>
<li>Object.assign()</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj1 =&#123;<span class="attr">name</span>:<span class="string">'tom'</span>,<span class="attr">age</span>:<span class="number">12</span>,<span class="attr">addr</span>:&#123;<span class="attr">lng</span>:<span class="number">26.0</span>,<span class="attr">lag</span>:<span class="number">45.0</span>&#125;,<span class="attr">friends</span>:[<span class="string">'john'</span>,<span class="string">'jerry'</span>]&#125;</span><br><span class="line"><span class="keyword">let</span> obj2= <span class="built_in">Object</span>.assign(&#123;&#125;, obj1);</span><br></pre></td></tr></table></figure>

<p>与解构赋值的作用一样</p>
<ul>
<li>lodash.clone()</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> objects = [&#123; <span class="string">'a'</span>: <span class="number">1</span> &#125;, &#123; <span class="string">'b'</span>: <span class="number">2</span> &#125;];</span><br><span class="line"> </span><br><span class="line"><span class="keyword">var</span> shallow = _.clone(objects);</span><br><span class="line"><span class="built_in">console</span>.log(shallow[<span class="number">0</span>] === objects[<span class="number">0</span>]);</span><br></pre></td></tr></table></figure>



<h3 id="深拷贝"><a href="#深拷贝" class="headerlink" title="深拷贝"></a>深拷贝</h3><ul>
<li>主要针对于引用类型，他会在对上面重新开辟一空间存放对象，这样两个深拷贝的对象就不会互相影响了</li>
</ul>
<h4 id="实现方式-1"><a href="#实现方式-1" class="headerlink" title="实现方式"></a>实现方式</h4><ul>
<li>JSON.parse(JSON.stringfy() )</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj1 =&#123;<span class="attr">name</span>:<span class="string">'tom'</span>,<span class="attr">friends</span>:[<span class="string">'jerry'</span>,<span class="string">'john'</span>]&#125;</span><br><span class="line"><span class="keyword">let</span> obj2 =<span class="built_in">JSON</span>.parse(<span class="built_in">JSON</span>.stringify(obj1))</span><br><span class="line">obj2.name=<span class="string">'jerry'</span></span><br><span class="line">obj2.friends[<span class="number">0</span>]=<span class="string">'tom'</span></span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/baifangzi/blogimage/raw/master/img/20210702134923.png" alt="image-20210702134922212"></p>
<ul>
<li>lodash.cloneDeep()</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> objects = [&#123; <span class="string">'a'</span>: <span class="number">1</span> &#125;, &#123; <span class="string">'b'</span>: <span class="number">2</span> &#125;];</span><br><span class="line"> </span><br><span class="line"><span class="keyword">var</span> deep = _.cloneDeep(objects);</span><br><span class="line"><span class="built_in">console</span>.log(deep[<span class="number">0</span>] === objects[<span class="number">0</span>]);</span><br></pre></td></tr></table></figure>

<ul>
<li>递归遍历实现</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">clone</span>(<span class="params">targetObj</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//判断是否未对象，是对象去遍历拷贝</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> targetObj === <span class="string">'object'</span>) &#123;</span><br><span class="line">        <span class="comment">//判断源数据是对象还是数组</span></span><br><span class="line">        <span class="keyword">let</span> cloneTarget = <span class="built_in">Array</span>.isArray(targetObj) ? [] : &#123;&#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">const</span> key <span class="keyword">in</span> targetObj) &#123;</span><br><span class="line">            <span class="comment">//递归拷贝</span></span><br><span class="line">            cloneTarget[key] = clone(targetObj[key])</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> cloneTarget</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">//不是对象直接返回</span></span><br><span class="line">        <span class="keyword">return</span> targetObj</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


        </div>

        
        <section class="post-tags">
            <div>
                <span>标签：</span>
                <span class="tag">
                    
                    
                        <a href="/tag/JS/"># JS</a>
                    
                        
                </span>
            </div>
            <div>
                <a href="javascript:window.history.back();">返回</a>
             
                <a href="/">回到首页</a>
            </div>
        </section>
        <section class="post-nav">
            
                <a class="prev" rel="prev" href="/2021/08/23/JS%E5%8E%9F%E5%9E%8B%E4%B8%8E%E5%8E%9F%E5%9E%8B%E9%93%BE/">JS原型与原型链</a>
            
            
            <a class="next" rel="next" href="/2019/04/24/js/">Hexo 添加分类及标签</a>
            
        </section>

    </article>
</div>

        </div>
        <footer id="footer" class="footer">
  <script type="text/javascript">document.write(unescape("%3Cspan id='cnzz_stat_icon_1280228628'%3E%3C/span%3E%3Cscript src='https://s9.cnzz.com/z_stat.php%3Fid%3D1280228628%26online%3D1%26show%3Dline' type='text/javascript'%3E%3C/script%3E"));</script>
</footer>

    </div>
</body>
</html>
